package com.fcc.wfly.base.controller;

import com.fcc.wfly.common.domain.ErrorHandleConst;
import com.fcc.wfly.common.service.CommonService;
import com.fcc.wfly.utils.AuthUtils;
import org.apache.commons.collections.map.MultiValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public abstract class RestApiController<T> {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	protected CommonService commonService;

	private MultiValueMap res;

	protected static SimpleDateFormat DATEFORMAT_REQUEST = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

	public HttpEntity<T> process(HttpServletRequest request, HttpServletResponse response) {
		if (AuthUtils.auth(request)) {
			Map<String, String> params = getParamNames(request);
			RestApiLogger apiLogger = begin(request, params);
			try {
				T result = process(params);
				return new ResponseEntity<T>(result, HttpStatus.OK);
			} catch (Exception e) {
				if (e.getMessage()== ErrorHandleConst.PN_NOT_EMPTY){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.SN_NOT_EMPTY){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.SN_OVER_LIMIT){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.PN_OVER_LIMIT){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.DATE_NOT_EMPTY){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.DATE_ERROR_FORMAT){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.DURING_TIME){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.EVENT_CODE_NOT_EMPTY){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}
				else if(e.getMessage()==ErrorHandleConst.EVENT_CODE_OVER_LIMIT){
					logger.info("【{}】Bad Request:{}", getApiName(), e.getMessage());
					res = new MultiValueMap();
					res.put("error", e.getMessage());
				}

				return new ResponseEntity(res, HttpStatus.BAD_REQUEST);
			} finally {
				commonService.addRequestLog(apiLogger.end());
			}
		} else {
			return new ResponseEntity<T>(HttpStatus.UNAUTHORIZED);
		}
	}

	
	private Map<String, String> getParamNames(HttpServletRequest request) {
		String[] apiParamNames = getApiParamNames();
		Map<String, String> params = new HashMap<String, String>();
		for (String apiParamName : apiParamNames) {
			params.put(apiParamName, request.getParameter(apiParamName));
		}
		return params;
	}

	private RestApiLogger begin(HttpServletRequest request, Map<String, String> params) {
		RestApiLogger apiLogger = RestApiLogger.begin(getApiName(), request);
		for (Entry<String, String> entry : params.entrySet()) {
			apiLogger.addParamter(entry.getKey(), entry.getValue());
		}
		return apiLogger;
	}

	protected abstract String getApiName();

	protected abstract String[] getApiParamNames();

	protected abstract T process(Map<String, String> params) throws Exception;

}